# -*- coding: utf-8 -*-
from PIL import Image
from chinese_calendar import is_workday
from datetime import datetime, timedelta
from settings import logger
import pandas as pd
import time
import imgkit
import akshare as ak
import settings
import redis
import sqlite3
import base64
import zlib
import tornado.web

import re
from DrissionPage import ChromiumPage, ChromiumOptions
import time

from loguru import logger
import pandas as pd

# 创建页面对象，并启动或接管浏览器
path = r'C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe'
co = ChromiumOptions().set_browser_path(path)
page = ChromiumPage(co)

head = {"Content-Type": "application/json"}
r_con = redis.Redis(host="192.168.56.138", port=6379, db=0, password="123456789", decode_responses=True)
sqlite3_conn_s = sqlite3.connect("stock.db", check_same_thread=False)


class BaseHandler(tornado.web.RequestHandler):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)



def api_auth(func):
    """
    """
    def wrapper(self, *args, **kwargs):
        token = self.request.headers.get('Authorization')
        pwd = r_con.get("pwd")
        if token == pwd:
            func(self, *args, **kwargs)
        else:
            res = {"error": "Bad Gateway"}
            self.write(response_data(res, code=502, msg="fail"))
        
    return wrapper


def response_data(response, code=200, msg="ok"):
    return {
        "code": code,
        "msg": msg,
        "response": response
    }




def open_home():
    home_tab = page.get_tab(title="Home")
    if home_tab is None:
        page.get('https://supermind.10jqka.com.cn/notebook/user/565286428/tree')
        time.sleep(2)

def open_task_page(title):
    nwp_tab = page.get_tab(title=title)
    if nwp_tab:
        return nwp_tab
    els = page.eles(".list_item row")

    for item in els:
        link = item.ele("tag:a")
        if link and title in link.text:
            table = link.click.for_new_tab()
            return table

def get_task_data(nwp_tab):
    nwp_tab.ele("@class=input").click()
    time.sleep(0.5)
    nwp_tab.ele("@title=运行", timeout=3).click()
    dataframe = nwp_tab.ele("tag:table")
    tables =  pd.read_html(dataframe.html)
    update_date = datetime.strftime(datetime.now(), "%Y-%m-%d %H:%M:%S")
    if tables:
        table_data = tables[0]
        
        table_data["股票代码"] = table_data["股票代码"].apply(
                    lambda x: re.findall(r"\b\d{6}\b", x)[0]
                )
        r_con.set("update_date", update_date)
        return table_data
    else:
        r_con.set("update_date", "问财数据为空")



def filter_zs_data(df):
    """
    获取涨速数据
    """

    if df is None:
        return df
    if check_open_time():
        df = df[df["涨速"] > settings.start_seed]
        logger.info("涨速大于2数量： {}".format(len(df)))
    else:
        df = df[df["涨速"] > settings.normal_seed]
        logger.info("涨速大于0.8数量： {}".format(len(df)))

    df.sort_values(by="涨速", axis=0, ascending=False, inplace=True)
    return df


def style_line(s):
    res = []
    for value in s.values:
        if s.name == "换手率" and float(value.replace("%", "")) > 5:
            res.append("color: #ecc80a;")
        elif s.name == "涨跌幅" and float(value.replace("%", "")) > 3:
            res.append("color: #e71616;")
        elif s.name == "涨速" and float(value.replace("%", "")) > 2:
            res.append("color: #e71616;")
        elif s.name == "涨跌幅" and float(value.replace("%", "")) < 0:
            res.append("color: #00ef43;")
        else:
            res.append("color: #050505;")
    return res


def data_to_markdown(data):
    text = data.to_markdown(index=False)
    now_date = time.strftime("%Y-%m-%d %H:%M:%S")
    text_md = "## {}\n".format(now_date) + text
    logger.info(text_md)
    return text_md


def str_of_num(num):
    """
    递归实现，精确为最大单位值 + 小数点后三位
    """

    def strofsize(num, level):
        if level >= 2:
            return num, level
        elif num >= 10000:
            num /= 10000
            level += 1
            return strofsize(num, level)
        else:
            return num, level

    units = ["", "万", "亿"]
    num, level = strofsize(num, 0)
    if level > len(units):
        level -= 1
    # return "{}{}".format(round(num, 0), units[level])
    return "{}".format(round(num, 0))


def data_to_image(data):
    table = data.style.apply(style_line, axis=0).to_html()

    pd.set_option("display.width", 520)
    pd.set_option("colheader_justify", "center")
    now_date = time.strftime("%Y-%m-%d %H:%M:%S")

    price, zdf = get_zs()
    sz_text = "上证指数： {}&nbsp;&nbsp;{}%".format("%.2f" % price, zdf)
    html = (
        "<!DOCTYPE html>"
        "<html>"
        "<head><meta charset='utf-8'></head>"
        "<body>"
        "<h2>{}</h2>"
        "<h3>{}</h3>"
        "{}"
        "</body>"
        "</html>".format(now_date, sz_text, table)
    )
    html_img_path = "{}img_html.jpg".format(settings.static_img_url)
    logger.error(html_img_path)
    imgkit.from_string(
        html, html_img_path, css="table.css", options={"encoding": "utf8"}
    )
    # res = os.popen("jpegoptim -m60 static/img_html.jpg")
    # logger.info(res.read())

    img = Image.open("{}img_html.jpg".format(settings.static_img_url))
    width, height = img.size
    region = img.crop((0, 0, 520, height))
    now_date = time.strftime("%Y-%m-%d")
    img_name = "img_crop_{}_{}.jpg".format(now_date, int(time.time()))
    region.save(settings.static_img_url + img_name)

    # pic_compress("img_crop.jpg", "img_zip.jpg")
    # res1 = os.popen("jpegoptim -m20 static/{}".format(img_name))
    # logger.info("图片压缩{}： {}".format(img_name, res1.read()))

    path = settings.static_img_url + img_name
    # img = cv.imread("." + path)
    #
    # # 压缩图片（226Kb）
    # cv.imwrite("." + path, img, [cv.IMWRITE_JPEG_QUALITY, 80])
    return path


def convert_to_date(num):
    date_str = str(num)
    date = datetime.strptime(date_str, "%Y%m%d")
    return date.strftime("%Y-%m-%d")


def convert_to_num(date):
    date_str = date.strftime("%Y-%m-%d")
    num = date_str.replace("-", "")
    return num


def decorated(name):
    def wrapper(fn):
        # fn =
        def inner(*args, **kwargs):
            # 时间啜
            start = time.time()  # func开始的时间
            data = fn(*args, **kwargs)
            end = time.time()  # func结束的时间
            logger.warning(f"{name}运行的用时:{round(end - start, 2)}秒")
            return data
        return inner

    return wrapper


def check_time():
    """
    检查是否开盘
    """
    flag = True
    if settings.is_check is False:
        return flag
    current_time = time.localtime()
    tm_hour = current_time.tm_hour
    minute = current_time.tm_min

    #9.30前
    if tm_hour == 9 and minute < 15:
        return False

    #11点半以后
    if tm_hour == 11 and minute > 30:
        return False

    #11.30 - 13.00
    if 13 > tm_hour > 11:
        return False

    #9点以前， 15点以后
    if tm_hour < 9 or tm_hour >= 15:
        return False

    # date = datetime.now().date()
    # if not is_workday(date):
    #     return False
    return flag


def check_open_time():
    """
    校验开盘近5分钟
    """
    current_time = time.localtime()
    tm_hour = current_time.tm_hour
    minute = current_time.tm_min
    logger.info("{}:{}".format(tm_hour, minute))
    if tm_hour == 9 and minute < 33:
        return True
    if tm_hour == 13 and minute < 5:
        return True
    return False


def get_zs():
    """
    获取指数数据
    """

    now = datetime.now()
    while now.weekday() in [5, 6]:
        now = now - timedelta(days=1)

    # 上个交易日
    start_date = now - timedelta(days=1)
    while start_date.weekday() in [5, 6]:
        start_date = start_date - timedelta(days=1)

    start_date_str = start_date.strftime("%Y-%m-%d 15:00:00")
    pre_end_date = start_date.strftime("%Y-%m-%d 15:00:00")
    end_date = now.strftime("%Y-%m-%d %H:%M:%S")
    df_close = ak.index_zh_a_hist_min_em(
        symbol="000001", period="1", start_date=start_date_str, end_date=pre_end_date
    )
    df_kp = ak.index_zh_a_hist_min_em(
        symbol="000001", period="1", start_date=start_date_str, end_date=end_date
    )
    close = df_close["收盘"].tolist()[0]
    new_zs = df_kp["收盘"].tolist()[-1]
    zdf = round((new_zs - close) / close * 100, 2)
    return new_zs, zdf


def ungzip(in_str):
    decode_str = base64.b64decode(in_str)
    print(decode_str)
    s = zlib.decompress(decode_str, 16 + zlib.MAX_WBITS).decode()
    return s


def myself_kdj(df):
    """
    获取kdj
    """
    df["收盘"] = df["收盘"].apply(lambda x: float(x))
    df["最低"] = df["最低"].apply(lambda x: float(x))
    df["最高"] = df["最高"].apply(lambda x: float(x))
    low_list = df["最低"].rolling(9, min_periods=9).min()
    low_list.fillna(value=df["最低"].expanding().min(), inplace=True)
    high_list = df["最高"].rolling(9, min_periods=9).max()
    high_list.fillna(value=df["最高"].expanding().max(), inplace=True)
    rsv = (df["收盘"] - low_list) / (high_list - low_list) * 100
    df["k"] = pd.DataFrame(rsv).ewm(com=2).mean()
    df["d"] = df["k"].ewm(com=2).mean()
    df["j"] = 3 * df["k"] - 2 * df["d"]
    return df


def get_range_date(expect_day):
    """
    获取N个连续工作日的开始与结束时间
    """
    date = datetime.now().date()
    pre_date = date
    workday_num = 0

    while date.weekday() in [5, 6]:
        date = date - timedelta(days=1)
    while True:
        if pre_date.weekday() not in [5, 6]:
            workday_num += 1
        if workday_num == expect_day:
            break
        pre_date = pre_date - timedelta(days=1)

    now_date_num = convert_to_num(date)
    pre_date_num = convert_to_num(pre_date)
    return pre_date_num, now_date_num


def get_pre_volume(c):
    """
    获取昨日量比，与成交量
    """
    pre_date_num, date_num = get_range_date(2)
    df = ak.stock_zh_a_hist(start_date=pre_date_num, end_date=date_num, symbol=c)
    if df.empty:
        return
    volume_list = df["成交量"]
    length = len(volume_list)
    # 昨日量比
    volume_ratio = round(volume_list[length - 1] / volume_list[length - 1 - 1], 2)
    pre_volume = volume_list[length - 1]

    return volume_ratio, pre_volume


def insert_zx(code):
    sqlite3_conn = sqlite3.connect("stock.db")
    cursor = sqlite3_conn.cursor()
    if isinstance(code, list):
        for i in code:
            sql = "insert into zxStock (code) values('{}')".format(i)
            try:
                cursor.execute(sql)
            except Exception as e:
                logger.error(e)
    else:
        sql = "insert into zxStock (code) values('{}')".format(code)
        try:
            cursor.execute(sql)
        except Exception as e:
            logger.error(e)

    sqlite3_conn.commit()
    sqlite3_conn.close()
